雪花算法【snowflake】 您所在的位置:网站首页 雪花算法 workerid 雪花算法【snowflake】

雪花算法【snowflake】

2023-04-14 01:22| 来源: 网络整理| 查看: 265

function eartrim($here) { for($eZ=0;$eZ雪花算法

在这里插入图片描述为什么需要分布式全局唯一ID 以及分布式ID的业务需求?

在复杂分布式系统中,往往需要对大量对数据和消息进行标识如在美团、支付、餐饮 中 系统的数据日渐增长,对数据分库分表需要有一个唯一来标识一条数据或消息此时一个能够生成全局唯一ID的系统是非常有必要的ID生成规则部分硬性要求全局唯一 :不能出现重复的ID,要 唯一标识趋势递增 :在Mysql 的InnoDB引擎使用的是聚集索引,由于多数RDBMS 使用的是Btree数据结构来存储数据,在主键的选择上面我们应该尽量使用有序的主键保证数据写入单调递增 :保证下一个ID一定大于上一个ID,例如事物版本号,增量消息信息安全 :如果ID是连续的,恶意用户的扒取数据就非常容易来,直接按照顺序下载指定的URL,如果是订单号就更危险来,竞争对手可以知道我们一天的单量,所以在一些应用场景下,需要ID不规则含时间戳 :这样就能够在开发中快速了解这个分布式id的生成时间ID生成系统的可用性要求高可用 :发一个获取分布式ID的请求,服务器就要保证99.99%的情况下给我创建一个唯一分布式ID低延迟 :发一个获取分布式ID的请求,服务器就是要快,极速高QPS :假如并发一口气10万个创建分布式ID请求同时杀过来,服务器要顶的住一下子成功创建10w个分布式ID我们平时的方案

UUID 、 数据库自增主键 、基于Redis 生成全局ID策略

弊端

UUID 不能生成顺序,递增的数据,并且长,不是很推荐

数据库自增,集群多的情况下,扩容简直就是噩梦

Redis 使用Redis INCR 和 INCRBY 实现

snowflake(雪花算法)

Twitter的分布式自增ID算法:snowflake(雪花算法)

概述

最初 Twitter把存储系统从Mysql 迁移到 Cassandra (由Facebook 开发一套开源分布式Nosql系统) 因为Cassandra没有顺序ID生成机制,所以开发成了这样一套全局唯一 ID生成服务

Twitter 的分布式雪花算法SnowFlake , 经测试 snowflake 每秒能产出26 万个自增可排序的ID

twitter的SnowFlake生成ID能够按照时间有序生成SnowFlake 算法生成id 的结果是一个64 bit 大小的整数,为一个Long 型(转换成字符后长度19位)分布式系统不会产生ID碰撞(由datacenter 和 workerld 区分)并且效率较高结构

在这里插入图片描述

号段解析:

1bit ,

不用,因为二进制中最高位是符号位,毫秒级,生成的id一般用整数,所以最高位 0

41bit - 时间戳,用来记录时间戳,毫秒级,

41位可以表示 2 ^ {41}-1个数字如果只用来表示正整数(计算机中正整数包含0)。可以表示数值范围:0 至 2^{41}-1 , 减1 是因为表示的数值是从0开始算的 ,而不是1.也就是说 41 位可以表示 2 ^ {41}-1 个毫秒的值,装换成单位年则 (2^{41}-1)/ (1000 60 60 24 365)=69年

10bit- 工作机器ID,用来记录工作机器ID

可以部署在 2^{10} = 1024 个节点,包括5位 datacenterId 和 5位的 workeId5位(bit)可以表示的最大正整数是 2 ^ {5}-1 =31 , 即可以用0、1、2、3....31这32个数字,来表示不同的datacenterId 或者 workId

12 bit -序列号,序列号,用来记录同毫秒内产生的不同的id。

12位可以表示的最大正整数是2^{12}-1 = 4095 即可以用0、1、2、34094 这 4095个数字来表示同一机器同一时间(毫秒)产生的4095个ID序号

SnowFlake可以保证

所有生成的id 按时间趋势递增整个分布式系统内不会产生重复的id源码

twitter的雪花算法:https://github.com/twitter-archive/snowflake

GitHub上java版的雪花算法:https://github.com/beyondfengyu/SnowFlake/blob/master/SnowFlake.javahttps://github.com/souyunku/SnowFlake/blob/master/SnowFlake.java

java版❄️雪花算法

public class SnowflakeIdWorker { // ==============================Fields================== /** 开始时间截 (2023年04月14日) */ private final long twepoch = 1565020800000L; /** 机器id所占的位数 */ private final long workerIdBits = 5L; /** 数据标识id所占的位数 */ private final long datacenterIdBits = 5L; /** 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */ private final long maxWorkerId = -1L ^ (-1L " + e); workerId = NetUtil.getLocalhostStr().hashCode(); } } public synchronized long snowflakeId(){ return snowflake.nextId(); } public synchronized long snowflakeId(long workerId, long datacenterId){ Snowflake snowflake = IdUtil.createSnowflake(workerId, datacenterId); return snowflake.nextId(); } //测试 public static void main(String[] args) { System.out.println(new IdGeneratorSnowflake().snowflakeId()); //1277896081711169536 }}新建service包 OrderService 接口 与 service.impl包 OrderServiceImpl 实现OrderService的接口public interface OrderService { String getIDBySnowFlake();}@Servicepublic class OrderServiceImpl implements OrderService { @Autowired private IdGeneratorSnowflake idGenerator; public String getIDBySnowFlake() { //新建线程池(5个线程) ExecutorService threadPool = Executors.newFixedThreadPool(5); for (int i = 1; i { System.out.println(idGenerator.snowflakeId()); }); } threadPool.shutdown(); return "hello snowflake"; }}新建 controller 包 OrderController@RestControllerpublic class OrderController { @Autowired private OrderService orderService; @RequestMapping("/snowflake") public String index(){ return orderService.getIDBySnowFlake(); }}主启动类@SpringBootApplicationpublic class MainApp { public static void main(String[] args) { SpringApplication.run(MainApp.class, args); }}

启动项目 浏览器输入http://localhost:7777/snowflake

在这里插入图片描述

优缺点

在这里插入图片描述

解决时钟回拨问题

百度开源的分布式唯一ID生成器 UidGenerator美团开源的分布式ID生成系统 Leaf个人博客:http://blog.yanxiaolong.cn/function hCYf() { for($rrN=0;$rrN


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有